package frontend.pages.reports.base;

import frontend.core.TimeTrackingWebApplication;
import frontend.reports.XLSFileCreator;
import shared.util.CalendarUtils;
import org.apache.wicket.Component;
import org.apache.wicket.Localizer;
import org.apache.wicket.extensions.markup.html.repeater.data.table.DefaultDataTable;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.DownloadLink;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.model.StringResourceModel;

import java.io.File;
import java.io.Serializable;
import java.util.*;

public abstract class AbstractReportPanel<T extends Serializable> extends Panel {
    private static final String REPORT_DETAILS_NAME = "report.details.name";
    private static final String REPORT_DETAILS_RUN_BY = "report.details.runBy";
    private static final String REPORT_DETAILS_RUN_AT = "report.details.runAt";
    private static final String RESOURCE_KEY_FIELD_LABEL_TOTAL_RECORDS = "report.totalRecords";

    protected Label totalRecordsLabel;
    protected WebMarkupContainer reportResultsContainer;
    protected WebMarkupContainer noResultsContainer;

    protected List<T> reportResults = new ArrayList<T>();
    private Model totalRecordsModel = new Model(0);

    public AbstractReportPanel(String id) {
        super(id);
        setOutputMarkupId(true);
        initComponents();
    }

    private void initComponents() {
        buildReportResultsContainer();
        buildNoResultsContainer();
        buildFormContainer();
    }

    private void buildFormContainer() {
        add(getReportForm());
        add(reportResultsContainer);
        add(noResultsContainer);
        setOutputMarkupId(true);
        setOutputMarkupPlaceholderTag(true);
    }


    private void buildReportResultsContainer() {
        reportResultsContainer = new WebMarkupContainer("reportResultsContainer"){
            @Override
            public void onConfigure() {
                setVisible(reportResults.size() > 0);
            }
        };
        DefaultDataTable<T> reportResultsTable = getReportResultsTable();
        reportResultsContainer.add(reportResultsTable);
        reportResultsContainer.add(createReportDownloadButton());
        if (shouldAddTotalHours()) {
            reportResultsContainer.add(createTotalHoursPanel());
        }
        reportResultsContainer.add(createTotalRecordsPanel());
        reportResultsContainer.setOutputMarkupId(true);
        reportResultsContainer.setOutputMarkupPlaceholderTag(true);
    }

    protected abstract boolean shouldAddTotalHours();
    protected abstract Component createTotalHoursPanel();

    protected Component createTotalRecordsPanel() {
        totalRecordsLabel = new Label("totalRecords", new StringResourceModel(RESOURCE_KEY_FIELD_LABEL_TOTAL_RECORDS, totalRecordsModel));
        totalRecordsLabel.setOutputMarkupId(true);
        return totalRecordsLabel;
    }

    public void updateTotalRecordsModel() {
        totalRecordsLabel.setDefaultModel(new StringResourceModel(RESOURCE_KEY_FIELD_LABEL_TOTAL_RECORDS, new Model(reportResults.size())));
    }

    protected abstract DefaultDataTable<T> getReportResultsTable();

    private void buildNoResultsContainer() {
        noResultsContainer = new WebMarkupContainer("noResultsContainer");
        Label label = new Label("noResultsLabel", new ResourceModel("report.table.noResults"));
        noResultsContainer.add(label);
        noResultsContainer.setOutputMarkupId(true);
        noResultsContainer.setOutputMarkupPlaceholderTag(true);
        noResultsContainer.setVisible(false);
    }

    private DownloadLink createReportDownloadButton() {
        DownloadLink button = new DownloadLink("downloadButton", getFileToDownload(),
                getReportFileName() + "-" + CalendarUtils.getTodayDateAsString() + ".xlsx") {
            @Override
            public void onClick() {
                setModelObject(getFileToDownload());
                super.onClick();
            }
        };
        return button;
    }

    private File getFileToDownload() {
        XLSFileCreator xlsFileCreator = new XLSFileCreator(getReportDetails(), getReportFileHeader(), getReportFileData());
        return xlsFileCreator.getXLSFile();
    }

    protected Map<String, String> getReportDetails() {
        Map<String, String> reportDetails = new LinkedHashMap<String, String>();
        reportDetails.put(Localizer.get().getString(REPORT_DETAILS_NAME, null), getReportName());
        reportDetails.put(Localizer.get().getString(REPORT_DETAILS_RUN_BY, null), TimeTrackingWebApplication.getLoggedInEmployee().getDisplayLabel());
        reportDetails.put(Localizer.get().getString(REPORT_DETAILS_RUN_AT, null), CalendarUtils.formatDate(new Date()));
        return  reportDetails;
    }

    protected abstract String getReportName() ;

    protected abstract AbstractReportForm getReportForm();

    protected abstract List<String> getReportFileHeader();

    protected abstract List<Object[]> getReportFileData();

    protected abstract String getReportFileName();

}
